<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title></title>
	<link rel="stylesheet" href="">
</head>
<body>
<script src='http://cdn.jsdelivr.net/vue/1.0.26/vue.js'></script>
<script src='https://cdn.jsdelivr.net/vue.router/0.7.10/vue-router.min.js'></script>
<div id="root">
	  <ul>
	    <li v-for="(val, key, index) in me">{{index}}. {{key}}: {{val}}</li>
	  </ul>
	  <ul>
	  	<li v-for="(item , index) in items">{{index}}:{{item}}</li>
	  </ul>
	  <ul>
	  	<li v-for="i in n">{{i}}</li>
	  </ul>
	  <ul>
	  	<li v-for="person in persons">名字是:{{person.name}},年龄为:{{person.age}},序号为:{{$index}}</li>
	  </ul>
	  <ul>
	  	<li v-for="person in persons" v-if='person.age>22'>名字是:{{person.name}},年龄为:{{person.age}},序号为:{{$index}}</li>
	  </ul>
	  <ul>
	  	<li v-for="i in arr">{{i}}</li>
	  </ul>
</div>	
<script>
	var aaa = [];
	var vm = new Vue({
		el : '#root',
		data : {
		    me: {
		      name: 'Dale',
		      age: 22,
		      sex: 'male',
		      height: 170
		    },
		    items : ['apple', 'tomato', 'banana', 'watermelon'],
		    n : 5,
		    persons: [
			      {
			        name: 'Dale',
			        age: 22,
			        id : 0
			      }, 
			      {
			        name: 'Tim',
			        age: 30,
			        id : 1
			      },
			      {
			        name: 'Rex',
			        age: 23,
			        id : 2
			      }
   			 ],
   			arr : [1,2,3],
   			aaa : aaa,

		}
	});
	aaa.push = function(){
		console.log(1);
	}
	aaa.push();
	console.log(Array.prototype.push.toString());
	console.log(aaa.hasOwnProperty('push'));
/**
 * 这里，v-for 接收的参数相对较复杂，
 * 但是可以分为三个部分：
 * （1）括号及其内的遍历结果信息（val, key, index）
 * 其中，val 是遍历得到的属性值，key 是遍历得到的属性名，index 是遍历次序，这里的 key/
 * index都是可选参数，如果不需要，这个指令其实可以写成 v-for="val in me"；
 * （2）遍历关键词 in
 * in 可以使用 of 替代，官方的说法是“它是最接近 JavaScript 迭代器的语法”，但其实使用上并没有任何区别；
 * （3）被遍历对象 me
 * me 是绑定在实例 data属性上的一个属性，实际上，它是有一个执行环境的，也即是我们接触最多的 vue
 * 实例，模板中，我们仍旧可以像在 methods 以及计算属性中一样，通过 this 访问到它，这里的 me 其实就相当于
 * this.me，模板中直接写 this.me 也是可行的。
 */
/**
 * 二、实际应用
 * （一）对象、数组 & 组件
 * 实际应用过程中，
 * 我们单独使用数组或者对象去描述我们的数据的情况很少，
 * 更常见的模式是结合了数组和对象两部分内容：
 */
/**
 * （二）与 v-if 组合
 * 添加了 v-for 指令的标签，实际上也可以同时添加 v-if 指令，但值得注意的是，
 * v-for 的优先级更高，渲染模板时，相当于对每次遍历的结果进行了一次条件判断。
 */
/**
 * 如果要让 v-if 指令的优先级更高，可以考虑在 v-for 指令所绑定的标签的父级上添加 v-if 指令。
 */
/**
 * 三、注意事项
 * （一）key
 * 与 v-for 一样，在不绑定 key 属性的情况下，vue 
 * 默认会重用元素以提高性能，如果不需要它的默认行为，显式绑定一个唯一的 key 即可。
 */
/**
 * （二）数据 -> 视图更新
 * vue 的视图更新是依赖于 getter/setter 的，
 * 如果直接修改、增加、删除数组元素，并不会触发视图的更新。这里 vue 重写了如下方法：
 * push
 * pop
 * shift
 * unshift
 * splice
 * sort
 * reverse
 */
/**
 * 比如上面这种情况，如果我们想要在执行 arr 的 push 等方法，因为 push 是数组类型数据从 Array.prototype.push 
 * 继承过来的，所以我们一般情况下有两种实现方式。
 * （1）修改 Array.prototype
 * 1
 * 2
 * 3
 * 4
 * Array.prototype.push = function () {
 * console.log(1);
 * }
 * ([]).push();        // 1
 * 这里我们修改了 Array.prototype 上的 push 方法，但是实际上，整个 prototype 属性都可以被重写，如
 * Array.prototype =
 * xxx，这样做的好处很明显，在这一处进行修改，之后所有的数组类型都可以直接使用这个重写后的方法，
 * 实现和使用都非常简单；但是这样带来的副作用也特别明显，容易影响到其它的代码，其它使用这段代码的地方，除了功
 * 实现上可能受到影响外，效率上也会有较大影响，原生 js 的代码都是经过特殊优化的，我们重写实现，效率肯定会受到影
 * 响，最重要的是，如果大家的代码在同一个环境下运行，然后都尝试重写同一个方法的话，最终结果不言而喻。
 */
/*
	（2）增加自有方法
var arr = [];
 
arr.push = function () {
  console.log(1);
}
 
arr.push();         // 1
Array.prototype.push.toString();  // "function push() { [native code] }"
这里修改了 arr 的 push 方法， 但是并不涉及 Array.prototype.push，因为读写一个对象的属性/方法的时候，js 总是先尝试访问 “ownproperty”，也就是 “hasOwnProperty” 所检测的内容，这里我们姑且将其称为“自有属性（方法）”。读取数据的时候，如果没有读取到内容，那么 js 会尝试向上搜索 __proto__ 上的数据；写数据的时候，如果有这个自有属性，则会将其覆盖，如果没有，则将其作为自有属性添加到改对象上，而不会尝试将其添加到 __proto__ 上，这样的规则，也是为了防止“子类”以外修改“父类”的属性、方法等。这种实现方式虽然可以避免上面修改 Array.prototype 的一系列缺点，但是它的问题就更加明显，因为每次创建这样一个“数组”，就要重新实现/绑定这样一系列方法，它所带来的开发效率、性能问题不容小觑。

*/
/**
 * var base = [];
var arr = [];
 
base.push = function () {
  console.log(1);
};
arr.__proto__ = base;
arr.push();     // 1
arr.__proto__.push(); // 1
arr.__proto__.push.toString(); // "function push() { [native code] }"
实际上，vue 是利用了类似上面的方式，先创建了一个 Array 的实例，也就是一个数组类型的基础对象 base，然后为它添加了一个自有方法 push，最后用 base 覆盖了需要扩展的 arr 对象的 __proto__ 属性。
 */
/**
 * 这里需要重写 push 等方法的数组，我们只需要将其 __proto__ 指向 base 数组，在读新创建的数组的 push 的时候，发现它并没有这样一个自有方法，那么它就尝试读 __proto__ 上的方法，发现 __proto__ 属性（也即 base 数组）上有这样一个自有方法，那么它就不必再向上搜索而直接使用 base.push。
通过这种方式，我们不必为每一个数组重写一遍 push 方法，也不必去修改 Array.prototype ，看起来倒像是一个两全其美的方法。
 */
</script>	
</body>
</html>